#include <stdio.h>
#include <linux/fb.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <string.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <unistd.h>
#include "oled.h"
#include "oledfont.h"
int imag_w,imag_h;
static unsigned char *lcd_p=NULL;//屏幕缓存地址
static struct fb_fix_screeninfo fb_fix;//固定参数结构体
static struct fb_var_screeninfo fb_var;//可变参数结构体

int fd;

int OLED_Init(char *argv)
{
	/*1.打开设备*/
	fd=open(argv, 2);
	if(fd<0)
	{
		printf("打开设备失败\n");
	}
	/*2.获取固定参数*/
	memset(&fb_fix,0, sizeof(fb_fix));
 	ioctl(fd,FBIOGET_FSCREENINFO,&fb_fix);
	printf("屏幕缓存大小:%d\n",fb_fix.smem_len);
	printf("一行的字节数:%d\n",fb_fix.line_length);
	/*3.获取屏幕可变参数*/
	memset(&fb_var,0, sizeof(fb_var));
	ioctl(fd,FBIOGET_VSCREENINFO,&fb_var);
	printf("屏幕尺寸:%d*%d\n",fb_var.xres,fb_var.yres);
	printf("颜色位数:%d\n",fb_var.bits_per_pixel);

	/*4.将屏幕缓冲区映射到进程空间*/
	lcd_p=mmap(NULL,fb_fix.smem_len,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
	if(lcd_p==(void *)-1)
	{
		printf("内存映射失败\n");
		return -1;
        close(fd);
	}
	memset(lcd_p,0x00,fb_fix.smem_len);//将屏幕清空为白色
    return 0;
}

void unmap(void)
{
    //取消映射
	munmap(lcd_p,fb_fix.smem_len);
	close(fd);
}


/*LCD画点函数*/
void OLED_DrawPoint(int x,int y,int c)
{
	 unsigned char *p=NULL;//屏幕缓存地址
	if(fb_var.bits_per_pixel==8)
	{
		//获取要绘制的点的地址
		unsigned char *p= (unsigned char *)(lcd_p+y*fb_fix.line_length+x*fb_var.bits_per_pixel/8);
		*p=c;//写入颜色值
	}
	else
	{
		//获取要绘制的点的地址
		unsigned short *p= (unsigned char *)(lcd_p+y*fb_fix.line_length+x*fb_var.bits_per_pixel/8);
		*p=c;//写入颜色值
		
	}
}

void OLED_Clear(u8 color)
{
	memset(lcd_p,color,fb_fix.smem_len);
}

void OLED_ShowPicture(u8 x,u8 y,u8 sizex,u8 sizey,u8 BMP[],u8 mode)
{
	u16 j=0;
	u8 i,n,temp,m;
	u8 x0=x,y0=y;
	sizey=sizey/8+((sizey%8)?1:0);
	for(n=0;n<sizey;n++)
	{
		 for(i=0;i<sizex;i++)
		 {
            temp=BMP[j];
            j++;
            for(m=0;m<8;m++)
            {
                if(temp&0x01)OLED_DrawPoint(x,y,mode);
                else OLED_DrawPoint(x,y,!mode);
                temp>>=1;
                y++;
            }
            x++;
            if((x-x0)==sizex)
            {
                x=x0;
                y0=y0+8;
            }
            y=y0;
        }
    }
}

void OLED_ShowChar(u16 x,u16 y,u8 num,u8 sizey,u8 mode)
{
	u8 temp,sizex,t;
	u16 i,TypefaceNum;//一个字符所占字节大小
	u16 x0=x;
	sizex=sizey/2;
	TypefaceNum=sizex/8*sizey;
	num=num-' ';    //得到偏移后的值
	for(i=0;i<TypefaceNum;i++)
	{ 
		if(sizey==16)temp=ascii_1608[num][i];		       //调用8x16字体
		else if(sizey==32)temp=ascii_3216[num][i];		 //调用16x32字体
		else return;
		for(t=0;t<8;t++)
		{
			if(temp&(0x01<<t))OLED_DrawPoint(x,y,mode);//画一个点
			else OLED_DrawPoint(x,y,!mode);
			x++;
			if((x-x0)==sizex)
			{
				x=x0;
				y++;
				break;
			}
		}
	}   	 	  
}


void OLED_ShowString(u16 x,u16 y,const u8 *p,u8 sizey,u8 mode)
{         
	while(*p!='\0')
	{       
		OLED_ShowChar(x,y,*p,sizey,mode);
		x+=sizey/2;
		p++;
	}  
}


